#include "TFBondBboPushHandler.h"
#include "../../BondDataCenter.h"
#include <bondlib/BondContainer.h>
#include <QJsonArray>
#include <QJsonObject>
#include <uam/ServerTimeMgr.h>
#include <qbtools/tools.h>

bool BondBboPushHandler::processCmd(const QJsonObject& cmdObj, const ReqInfo& reqinfo, bool unReg)
{
	std::vector<std::string> bondKeys = parse(cmdObj);
	if (bondKeys.empty())
		return false;

	for (const auto& key : bondKeys)
		unReg ? removePush(key, reqinfo) : addPush(key, reqinfo);

	static bool s_connected = false;
	if (!unReg && !m_registerPushes.empty() && !s_connected)
	{
		connect(&BondDataCenter::instance(), &BondDataCenter::bestPriceArrived, this, &BondBboPushHandler::onBestPriceArrived);
		s_connected = true;
	}
	else if (unReg && m_registerPushes.empty() && s_connected)
	{
		disconnect(&BondDataCenter::instance(), &BondDataCenter::bestPriceArrived, this, &BondBboPushHandler::onBestPriceArrived);
		s_connected = false;
	}
		
	return true;
}

void BondBboPushHandler::onBestPriceArrived(std::string key, QList<xQBBestPriceUnit_c> prices)
{
	{
		std::lock_guard<std::mutex> locker(m_mutex);
		if (m_registerPushes.find(key) == m_registerPushes.end() && m_registerPushes.find("") == m_registerPushes.end())
			return;
	}
	

	CBondContainer& gc = CBondContainer::instance();
	int bondIndex = gc.GetBondIndex(key.c_str());
	if (!gc.IsValidIndex(bondIndex))return;

	const CBondInfo& bi = gc.ElementAtR(bondIndex);

	int count = 0;
	QJsonArray list;
	QJsonObject jsRes;

	QString ttm = QString::fromLocal8Bit(bi.GetRemainPeriod(ServerTimeMgr::instance().serverTime()));
	for (const auto& priceUnit : prices)
	{
		if(atoi(priceUnit.m_company_id) > 5)
			continue;

		REPORT rpt;
		if (!gc.GetCompanyRepByKey(bi.GetCombBondKey(), priceUnit.m_company_id, rpt))
			continue;

		QJsonObject item;
		item["combkey"] = bi.GetCombBondKey();
		item["code"] = bi.GetBondCode();
		item["listedmarket"] = bi.GetListedMarket();
		item["ttm"] = ttm;
		item["corp"] = priceUnit.m_company_id;

		bool bBidValid = true;
		bool bOfrValid = true;
		if (strcmp(rpt.m_bidinfo.m_price_status, "0") == 0)
		{
			bBidValid = false;
		}
		else
		{
			bBidValid = true;
		}

		if (strcmp(rpt.m_askinfo.m_price_status, "0") == 0)
		{
			bOfrValid = false;
		}
		else
		{
			bOfrValid = true;
		}

		// NAME://简称
		item["shortname"] = QString::fromLocal8Bit(bi.GetBondShortName());
		//Vol.Bid
		if (!bBidValid)
		{
			item["bidvol"] = "--";
		}
		else
		{
			item["bidvol"] = SSTools::StringRemoveZero(rpt.m_bidinfo.m_sVolume);
		}

		// Bid
		if (bBidValid)
		{
			item["bid"] = displayPrice(&rpt.m_bidinfo);
		}
		else
		{
			item["bid"] = "--";
		}
		// OFR:
		if (bOfrValid)
		{
			item["ofr"] = displayPrice(&rpt.m_askinfo);
		}
		else
		{
			item["ofr"] = "--";
		}
		// vol.ofr
		if (!bOfrValid)
		{
			item["ofrvol"] = "--";
		}
		else
		{
			item["ofrvol"] = SSTools::StringRemoveZero(rpt.m_askinfo.m_sVolume);
		}

		item["updatetime"] = (int)rpt.m_time;

		list.append(item);

		if (++count % 20 == 0)
		{
			jsRes["finish"] = 0;
			jsRes["list"] = list;

			QJsonDocument doc(jsRes);
			pushData(key, doc.toJson(QJsonDocument::Compact));

			QJsonObject emptyObj;
			QJsonArray emptyArr;
			jsRes.swap(emptyObj);
			list.swap(emptyArr);
		}
	}

	jsRes["finish"] = 1;
	jsRes["list"] = list;

	QJsonDocument doc(jsRes);
	pushData(key, doc.toJson(QJsonDocument::Compact));
}

std::vector<std::string> BondBboPushHandler::parse(const QJsonObject& cmdObj)
{
	std::vector<std::string> bondKeys;
	QJsonObject condObj = cmdObj["cond"].toObject();
	if (condObj.isEmpty())
	{
		bondKeys.emplace_back("");
		return bondKeys;
	}

	QJsonArray keyList = condObj["list"].toArray();
	if (keyList.isEmpty())
	{
		bondKeys.emplace_back("");
		return bondKeys;
	}

	for (auto item : keyList)
	{
		QJsonObject keyItem = item.toObject();
		QString key = keyItem["combkey"].toString();

		int bondIndex = -1;
		if (!key.isEmpty())
		{
			bondIndex = CBondContainer::instance().GetBondIndex(key.toUtf8().data());
		}
		else if (!(key = keyItem["combcode"].toString()).isEmpty())
		{
			bondIndex = CBondContainer::instance().GetBondInfoByCombCode(key.toUtf8().data(), nullptr, &bondIndex);
		}

		if (!CBondContainer::instance().IsValidIndex(bondIndex))continue;
		const CBondInfo& bi = CBondContainer::instance().ElementAtR(bondIndex);
		bondKeys.emplace_back(bi.GetCombBondKey());
	}

	return bondKeys;
}
